package com.milo.java8.optional;

import com.milo.java8.optional.entity.Inner;
import com.milo.java8.optional.entity.Nested;
import com.milo.java8.optional.entity.Outer;
import org.junit.Test;

import java.util.Optional;
import java.util.function.Supplier;

import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
 * @author: Milogenius
 * @create: 2019-06-05 08:58
 * @description:
 **/
public class OptionalTest {

    /**
     * 繁琐的代码判断空指针
     */
    @Test
    public void test1() {
        Outer outer = new Outer();
        if (outer != null & outer.nested != null & outer.nested.inner != null) {
            System.out.println(outer.nested.inner.foo);
        }
    }

    /**
     * Optional解决空指针
     */
    @Test
    public void test2() {
        Optional.of(new Outer())
                .map(Outer::getNested)
                .map(Nested::getInner)
                .map(Inner::getFoo)
                .ifPresent(System.out::println);// 如果不为空，最终输出 foo 的值
    }

    /**
     * 空指针终极解决方案
     *
     * @param resolver
     * @param <T>
     * @return
     */
    public static <T> Optional<T> resolve(Supplier<T> resolver) {

        try {
            T result = resolver.get();
            return Optional.ofNullable(result);
        } catch (NullPointerException e) {
            // 可能会抛出空指针异常，直接返回一个空的 Optional 对象
            return Optional.empty();
        }

    }

    /**
     * 测试终结解决方案
     */
    @Test
    public void test3() {
        Outer obj = new Outer();
        // 直接调用 resolve 方法，内部做空指针的处理
        resolve(() -> obj.getNested().getInner().getFoo())
                .ifPresent(System.out::println);
        // 如果不为空，最终输出 foo 的值
    }

    /**
     *创建某个值的Optional对象
     */
    @Test
    public void get(){
        Optional<String> a = Optional.of("a");
        assertEquals("a",a.get());
    }

    /**
     * 创建一个空的Optional对象,并检查是否有值
     */
    @Test
    public void test4(){
        Optional<String> a = Optional.of("a");
        Optional<Object> empty = Optional.empty();
        //如果为null,返回空的Optional,否则返回包含特定值得Optional
        Optional<Object> alsoEmpty = Optional.ofNullable(null);
        //isPresent 有值返回true
        assertFalse(empty.isPresent());
        assertTrue(a.isPresent());
        assertEquals("b",a.orElse("b"));
        //orElseGet:如果Optional有值,则返回,否则返回调用的值
        assertEquals("c",a.orElseGet(() -> "c"));
    }


}
